package com.battcn.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import com.battcn.framework.redis.JedisBuilder;
import com.battcn.framework.redis.RedisOperator;
import com.battcn.framework.redis.impl.RedisOperatorImpl;
import com.battcn.platform.cache.ManagerCacheAop;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Redis缓存配置类
 * 
 * @author szekinwin
 *
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

	@Value("${spring.redis.host}")
	private String host;
	@Value("${spring.redis.port}")
	private int port;
	@Value("${spring.redis.timeout}")
	private int timeout;
	@Value("${spring.redis.pool.max-idle}")
	private int maxidle;
	@Value("${spring.redis.password}")
	private String password;

	// 自定义缓存key生成策略
	// @Bean
	// public KeyGenerator keyGenerator() {
	// return new KeyGenerator(){
	// @Override
	// public Object generate(Object target, java.lang.reflect.Method method,
	// Object... params) {
	// StringBuffer sb = new StringBuffer();
	// sb.append(target.getClass().getName());
	// sb.append(method.getName());
	// for(Object obj:params){
	// sb.append(obj.toString());
	// }
	// return sb.toString();
	// }
	// };
	// }
	
	/*對應配置
	 * <bean id="builder" class="com.battcn.framework.redis.JedisBuilder"
	 * destroy-method="stop"> <constructor-arg index="0"
	 * type="java.lang.String"> <value>${battcn.redis.host}</value>
	 * </constructor-arg> <constructor-arg index="1" type="int">
	 * <value>${battcn.redis.port}</value> </constructor-arg> <constructor-arg
	 * index="2" type="int"> <value>2000</value> </constructor-arg>
	 * <constructor-arg index="3" type="int"> <value>5</value>
	 * </constructor-arg> <constructor-arg index="4" type="boolean">
	 * <value>true</value> </constructor-arg> <constructor-arg index="5"
	 * type="java.lang.String"> <value>${battcn.redis.password}</value>
	 * </constructor-arg> </bean>
	 */
	@Bean(destroyMethod = "stop")
	public JedisBuilder jedisBuilder() {
		return new JedisBuilder(host, port, timeout, maxidle, true, password);
	}

	/*对应配置
	 * <bean id="redisOperator"
	 * class="com.battcn.framework.redis.impl.RedisOperatorImpl"> <property
	 * name="builder" ref="builder"/> </bean>
	 */
	@Bean("redisOperator")
	public RedisOperator redisOperator() {
		RedisOperatorImpl redisOperator=new RedisOperatorImpl();
		redisOperator.setBuilder(jedisBuilder());
		return redisOperator;
	}
	/*
	 * <bean id="managerCache" class="com.battcn.platform.cache.ManagerCacheAop"/>*/
	@Bean("managerCache")
	public ManagerCacheAop managerCache(){
		return new ManagerCacheAop();
	}
	// 缓存管理器
	@Bean
	public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
		RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
		// 设置缓存过期时间
		cacheManager.setDefaultExpiration(10000);
		return cacheManager;
	}

	@Bean
	public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
		StringRedisTemplate template = new StringRedisTemplate(factory);
		setSerializer(template);// 设置序列化工具
		template.afterPropertiesSet();
		return template;
	}

	private void setSerializer(StringRedisTemplate template) {
		@SuppressWarnings({ "rawtypes", "unchecked" })
		Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(om);
		template.setValueSerializer(jackson2JsonRedisSerializer);
	}
}
